package server

import (
	"fmt"
	"net"

	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

// ServiceRegistrar 服务注册器接口
type ServiceRegistrar interface {
	RegisterServices(server *grpc.Server)
}

// GRPCServerManager 通用 gRPC 服务器管理器
type GRPCServerManager struct {
	server     *grpc.Server
	port       int
	logger     *zap.Logger
	registrars []ServiceRegistrar
}

// Config gRPC 服务器配置
type Config struct {
	Port                  int
	EnableReflection      bool
	MaxReceiveMessageSize int
	MaxSendMessageSize    int
}

// NewGRPCServerManager 创建新的 gRPC 服务器管理器
func NewGRPCServerManager(logger *zap.Logger, config *Config) *GRPCServerManager {
	// 创建 gRPC 服务器选项
	var opts []grpc.ServerOption

	if config.MaxReceiveMessageSize > 0 {
		opts = append(opts, grpc.MaxRecvMsgSize(config.MaxReceiveMessageSize))
	}

	if config.MaxSendMessageSize > 0 {
		opts = append(opts, grpc.MaxSendMsgSize(config.MaxSendMessageSize))
	}

	// 创建 gRPC 服务器
	server := grpc.NewServer(opts...)

	// 启用反射（开发环境有用）
	if config.EnableReflection {
		reflection.Register(server)
	}

	return &GRPCServerManager{
		server: server,
		port:   config.Port,
		logger: logger,
	}
}

// RegisterService 注册服务
func (m *GRPCServerManager) RegisterService(registrar ServiceRegistrar) {
	m.registrars = append(m.registrars, registrar)
}

// Start 启动 gRPC 服务器
func (m *GRPCServerManager) Start() error {
	// 注册所有服务
	for _, registrar := range m.registrars {
		registrar.RegisterServices(m.server)
	}

	// 监听端口
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", m.port))
	if err != nil {
		return fmt.Errorf("failed to listen on port %d: %w", m.port, err)
	}

	m.logger.Info("starting gRPC server",
		zap.Int("port", m.port),
		zap.Int("registered_services", len(m.registrars)))

	// 启动服务器（这会阻塞）
	if err := m.server.Serve(lis); err != nil {
		return fmt.Errorf("failed to serve gRPC: %w", err)
	}

	return nil
}

// Stop 停止 gRPC 服务器
func (m *GRPCServerManager) Stop() {
	m.logger.Info("stopping gRPC server")
	m.server.GracefulStop()
}

// GetServer 获取原始的 gRPC 服务器（用于高级配置）
func (m *GRPCServerManager) GetServer() *grpc.Server {
	return m.server
}
